#pragma once

#include <defines.h>
#include "color.h"

#ifdef __cplusplus
extern "C"
{
#endif

	typedef struct surface_t
	{
		int width;
		int height;
		int stride;
		int pixlen;
		color_t *pixels;
	} surface_t;

	typedef struct region_t
	{
		int x;
		int y;
		int w;
		int h;
	} region_t;

	static inline int region_isempty(region_t r)
	{
		if ((r.w > 0) && (r.h > 0))
			return 0;
		return 1;
	}

	static inline int region_hit(struct region_t r, int x, int y)
	{
		if ((x >= r.x) && (x < r.x + r.w) && (y >= r.y) && (y < r.y + r.h))
			return 1;
		return 0;
	}

	static inline int region_contains(struct region_t r, struct region_t o)
	{
		int rr = r.x + r.w;
		int rb = r.y + r.h;
		int or = o.x + o.w;
		int ob = o.y + o.h;
		if ((o.x >= r.x) && (o.x < rr) && (o.y >= r.y) && (o.y < rb) && (or > r.x) && (or <= rr) && (ob > r.y) && (ob <= rb))
			return 1;
		return 0;
	}

	static inline region_t region_intersect(region_t a, region_t b)
	{
		region_t r = {};

		int x0 = max(a.x, b.x);
		int x1 = min(a.x + a.w, b.x + b.w);
		if (x0 <= x1)
		{
			int y0 = max(a.y, b.y);
			int y1 = min(a.y + a.h, b.y + b.h);
			if (y0 <= y1)
			{
				r.x = x0;
				r.y = y0;
				r.w = x1 - x0;
				r.h = y1 - y0;
			}
		}
		return r;
	}

	static inline region_t region_union(region_t a, region_t b)
	{
		region_t r = {};
		int ar = a.x + a.w;
		int ab = a.y + a.h;
		int br = b.x + b.w;
		int bb = b.y + b.h;
		r.x = min(a.x, b.x);
		r.y = min(a.y, b.y);
		r.w = max(ar, br) - r.x;
		r.h = max(ab, bb) - r.y;
		return r;
	}

	surface_t *surface_alloc(int width, int height);
	surface_t *surface_copy(surface_t *s);
	void surface_free(surface_t *s);
	void surface_wrap(surface_t *s, color_t *c, int w, int h);
	surface_t *surface_alloc_wrap(color_t *c, int width, int height);
	void surface_clear(surface_t *s, color_t c, int x, int y, int w, int h);
	void surface_blit(surface_t *d, surface_t *s, int x, int y);
	void surface_cover(surface_t *d, surface_t *s, int x, int y);
	surface_t *surface_clone(surface_t *s, int x, int y, int w, int h);
	void surface_mono(surface_t *s, color_t color);
	void surface_filter_blur(struct surface_t *s, int radius);
	void surface_filter_opacity(struct surface_t *s, int a);
	void surface_mask(surface_t *d, surface_t *s, int x, int y);
	void surface_blit_region(surface_t *d, surface_t *s, region_t dst, region_t src);
	void surface_blit_region_xy(surface_t *d, surface_t *s, region_t dst, int x, int y);
	void surface_blit_with_opacity(surface_t *d, surface_t *s, int x, int y, int a);
	void surface_pixel_set(surface_t *s, color_t color, int x, int y);
	void surface_composite_out(surface_t *d, surface_t *s, int x, int y);

#ifdef __cplusplus
}
#endif